package xyz.labmem.lipx

import cn.hutool.core.comparator.VersionComparator
import cn.hutool.core.io.FileUtil
import cn.hutool.core.io.StreamProgress
import cn.hutool.core.io.file.FileReader
import cn.hutool.core.thread.ThreadUtil.sleep
import cn.hutool.http.HttpUtil
import it.sauronsoftware.junique.AlreadyLockedException
import it.sauronsoftware.junique.JUnique
import xyz.labmem.lipx.client.core.LabSSHPenetrationClient
import xyz.labmem.lipx.client.task.ClientAutoRunTask
import xyz.labmem.lipx.core.AppContext
import xyz.labmem.lipx.core.AppContext.Client.parallelPool
import xyz.labmem.lipx.core.console.Control
import xyz.labmem.lipx.core.console.enums.Display
import xyz.labmem.lipx.core.context.Secret
import xyz.labmem.lipx.core.tool.*
import xyz.labmem.lipx.core.util.ClientConfigDataUtil
import xyz.labmem.lipx.core.util.ServerConfigDataUtil
import java.io.File
import java.util.*
import kotlin.io.path.Path
import kotlin.system.exitProcess

val labVersion = VersionTool.getVersion()
val appAbsolutePath: String =
    File(LipxApplication::class.java.getProtectionDomain().codeSource.location.path).absolutePath

class LipxApplication

fun main(args: Array<String>) {
    var backgroundRun = false
    Thread {
        try {
            //获取秘钥参数
            var secretUrl: String? = null
            var hasUpdate = false
            var updateOldPath = ""
            args.forEach {
                if (it.startsWith("--secret:")) {
                    secretUrl = it.substringAfter("--secret:")
                }
                if (it.startsWith("--background")) {
                    backgroundRun = true
                }
                if (it.startsWith("--update_old_path:")) {
                    hasUpdate = true
                    updateOldPath = it.substringAfter("--update_old_path:")
                }
                if (it.startsWith("--debug"))
                    LogInfo.debug = true
                if (it.startsWith("--sbcMode"))
                    ConsoleTable.SbcMode = true
            }
            if (hasUpdate)
                updateRun(updateOldPath)
            else
                junique()
            val bar: ConsoleProgressBar? = if (!backgroundRun) ConsoleProgressBar(100, '✿', "LIPX配置装载中") else null
            bar?.show()
            if (secretUrl != null) {
                Secret(FileReader(secretUrl).readString())
            } else
                Secret(getResourceFile("secret.key").readUtf8Str())
            ClientConfigDataUtil.init()
            ServerConfigDataUtil.init()
            //服务自动启动
            if (AppContext.Server.cacheData!!.autoRun) {
                AppContext.Server.server.start(AppContext.Server.cacheData!!)
            }

            //客户端自动连接
            ClientAutoRunTask.start()
            bar?.stopLoop()
        } catch (e: Exception) {
            e.printStackTrace()
            shutdown()
        }
        if (!backgroundRun) {
            //检查更新
            try {
                ReqTool.checkUpdate {
                    if (VersionComparator.INSTANCE.compare(it.getString("code"), labVersion) > 0) {
                        if (Control.enquire("有新的版本${it.getString("code")}【${it.getString("remark")}】是否下载？")) {
                            var appType = "console.jar"
                            if (sysVersion.lowercase(Locale.getDefault()).contains("linux")) {
                                appType = "linux"
                            } else if (sysVersion.lowercase(Locale.getDefault()).contains("windows")) {
                                appType = "win.exe"
                            }
                            val url = ReqTool.getDownLoadUrl(it.getString("code"), appType)
                            HttpUtil.downloadFile(url, File(appPath), object : StreamProgress {
                                val bar = ConsoleProgressBar(50, '➹', "正在下载LIPX新版文件")
                                override fun start() {}
                                override fun progress(p0: Long, p1: Long) {
                                    bar.show(p1.div(p0 * 1.0) * 100)
                                }

                                override fun finish() {
                                    println("下载完成：$appPath")
                                    Thread {
                                        sleep(1000)
                                        openApp("$appPath/lipx-$appType", appType)
                                        shutdown()
                                    }.start()
                                }
                            })
                        }
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
                println("更新失败")
            }
            Control.render(Display.ROOT)
        } else {
            while (true) {
                Thread.sleep(1000)
            }
        }
    }.start()
}

fun shutdown() {
    println(" ♨ GL&HF! ♨ ")
    exitProcess(0)
}

fun junique() {
    try {
        JUnique.acquireLock(LipxApplication::class.java.name)
    } catch (e: AlreadyLockedException) {
        println("LIPX只能启动一个实例！")
        shutdown()
    }
}

fun updateRun(oldAppPath: String) {
    FileUtil.copy(Path(appAbsolutePath), Path(oldAppPath))
    println("更新成功!")
}

fun openApp(appPath: String, appType: String) {
    if ("win.exe" == appType) {
        Runtime.getRuntime().exec("cmd /c start $appPath --update_old_path:$appAbsolutePath")
    } else {
        println("run update code : cp $appPath $appAbsolutePath")
    }
}